Result SoundSourceSndFile::tryOpen(const AudioSourceConfig& /*audioSrcCfg*/) { DEBUG_ASSERT(!m_pSndFile); SF_INFO sfInfo; #ifdef __WINDOWS__ // Pointer valid until string changed const QString fileName(getLocalFileName()); LPCWSTR lpcwFilename = (LPCWSTR) fileName.utf16(); m_pSndFile = sf_wchar_open(lpcwFilename, SFM_READ, &sfInfo); #else memset(&sfInfo, 0, sizeof(sfInfo)); m_pSndFile = sf_open(getLocalFileNameBytes().constData(), SFM_READ, &sfInfo); #endif if (!m_pSndFile) { // sf_format_check is only for writes qWarning() << "Error opening libsndfile file:" << getUrlString() << sf_strerror(m_pSndFile); return ERR; } if (sf_error(m_pSndFile) > 0) { qWarning() << "Error opening libsndfile file:" << getUrlString() << sf_strerror(m_pSndFile); return ERR; } setChannelCount(sfInfo.channels); setFrameRate(sfInfo.samplerate); setFrameCount(sfInfo.frames); return OK; }
Result SoundSourceWV::tryOpen(const AudioSourceConfig& audioSrcCfg) { DEBUG_ASSERT(!m_wpc); char msg[80]; // hold possible error message int openFlags = OPEN_WVC | OPEN_NORMALIZE; if ((kChannelCountMono == audioSrcCfg.channelCountHint) || (kChannelCountStereo == audioSrcCfg.channelCountHint)) { openFlags |= OPEN_2CH_MAX; } m_wpc = WavpackOpenFileInput( getLocalFileNameBytes().constData(), msg, openFlags, 0); if (!m_wpc) { qDebug() << "SSWV::open: failed to open file : " << msg; return ERR; } setChannelCount(WavpackGetReducedChannels(m_wpc)); setFrameRate(WavpackGetSampleRate(m_wpc)); setFrameCount(WavpackGetNumSamples(m_wpc)); if (WavpackGetMode(m_wpc) & MODE_FLOAT) { m_sampleScaleFactor = CSAMPLE_PEAK; } else { const int bitsPerSample = WavpackGetBitsPerSample(m_wpc); const uint32_t wavpackPeakSampleValue = uint32_t(1) << (bitsPerSample - 1); m_sampleScaleFactor = CSAMPLE_PEAK / CSAMPLE(wavpackPeakSampleValue); } return OK; }
bool FCTimeline::init(void) { setSymbol(NULL); setFrameCount(0); setLayers(NULL); return true; }
SoundSource::OpenResult SoundSourceOpus::tryOpen(const AudioSourceConfig& /*audioSrcCfg*/) { // From opus/opusfile.h // On Windows, this string must be UTF-8 (to allow access to // files whose names cannot be represented in the current // MBCS code page). // All other systems use the native character encoding. #ifdef _WIN32 QByteArray qBAFilename = getLocalFileName().toUtf8(); #else QByteArray qBAFilename = getLocalFileName().toLocal8Bit(); #endif int errorCode = 0; DEBUG_ASSERT(!m_pOggOpusFile); m_pOggOpusFile = op_open_file(qBAFilename.constData(), &errorCode); if (!m_pOggOpusFile) { qWarning() << "Failed to open OggOpus file:" << getUrlString() << "errorCode" << errorCode; return OpenResult::FAILED; } if (!op_seekable(m_pOggOpusFile)) { qWarning() << "SoundSourceOpus:" << "Stream in" << getUrlString() << "is not seekable"; return OpenResult::UNSUPPORTED_FORMAT; } const int channelCount = op_channel_count(m_pOggOpusFile, kCurrentStreamLink); if (0 < channelCount) { setChannelCount(channelCount); } else { qWarning() << "Failed to read channel configuration of OggOpus file:" << getUrlString(); return OpenResult::FAILED; } const ogg_int64_t pcmTotal = op_pcm_total(m_pOggOpusFile, kEntireStreamLink); if (0 <= pcmTotal) { setFrameCount(pcmTotal); } else { qWarning() << "Failed to read total length of OggOpus file:" << getUrlString(); return OpenResult::FAILED; } const opus_int32 bitrate = op_bitrate(m_pOggOpusFile, kEntireStreamLink); if (0 < bitrate) { setBitrate(bitrate / 1000); } else { qWarning() << "Failed to determine bitrate of OggOpus file:" << getUrlString(); return OpenResult::FAILED; } setSamplingRate(kSamplingRate); m_curFrameIndex = getMinFrameIndex(); return OpenResult::SUCCEEDED; }
void MainScene::importFinish(vector<string> &vec) { m_state = CS_MAIN_PLIST; btnImport->setTitleText("导入"); xSkill->importPart(vec); setFrameCount(NULL); updateList(NULL); }
bool Planet::init() { if (!GameObject::init()) { return false; } _radius = 0; _density = 1; setTexturePath("planet_1.png"); setFrameCount(0); return true; }
//============================================================== // Чтение количества кадров из XML //============================================================== bool SettingAnimation::readFrameCountFromXml(QDomElement root) { const QDomElement elemFrameCount = root.firstChildElement("FrameCount"); if (elemFrameCount.isNull()) return false; const QString strFrameCount = elemFrameCount.text(); bool ok = false; const int frameCount = strFrameCount.toInt(&ok); if (!ok || (frameCount <= 0) || (frameCount > 100)) return false; setFrameCount(frameCount); return true; }
SoundSource::OpenResult SoundSourceSndFile::tryOpen(const AudioSourceConfig& /*audioSrcCfg*/) { DEBUG_ASSERT(!m_pSndFile); SF_INFO sfInfo; memset(&sfInfo, 0, sizeof(sfInfo)); #ifdef __WINDOWS__ // Note: we cannot use QString::toStdWString since QT 4 is compiled with // '/Zc:wchar_t-' flag and QT 5 not const QString localFileName(QDir::toNativeSeparators(getLocalFileName())); const ushort* const fileNameUtf16 = localFileName.utf16(); static_assert(sizeof(wchar_t) == sizeof(ushort), "QString::utf16(): wchar_t and ushort have different sizes"); m_pSndFile = sf_wchar_open( reinterpret_cast<wchar_t*>(const_cast<ushort*>(fileNameUtf16)), SFM_READ, &sfInfo); #else m_pSndFile = sf_open(getLocalFileName().toLocal8Bit(), SFM_READ, &sfInfo); #endif switch (sf_error(m_pSndFile)) { case SF_ERR_NO_ERROR: DEBUG_ASSERT(m_pSndFile != nullptr); break; // continue case SF_ERR_UNRECOGNISED_FORMAT: return OpenResult::UNSUPPORTED_FORMAT; default: const QString errorMsg(sf_strerror(m_pSndFile)); if (errorMsg.toLower().indexOf("unknown format") != -1) { // NOTE(uklotzde 2016-05-11): This actually happens when // trying to open a file with a supported file extension // that contains data in an unsupported format! return OpenResult::UNSUPPORTED_FORMAT; } else { qWarning() << "Error opening libsndfile file:" << getUrlString() << errorMsg; return OpenResult::FAILED; } } setChannelCount(sfInfo.channels); setSamplingRate(sfInfo.samplerate); setFrameCount(sfInfo.frames); return OpenResult::SUCCEEDED; }
bool SoundSourceMediaFoundation::readProperties() { PROPVARIANT prop; HRESULT hr = S_OK; //Get the duration, provided as a 64-bit integer of 100-nanosecond units hr = m_pSourceReader->GetPresentationAttribute(MF_SOURCE_READER_MEDIASOURCE, MF_PD_DURATION, &prop); if (FAILED(hr)) { qWarning() << kLogPreamble << "error getting duration"; return false; } setFrameCount(m_streamUnitConverter.toFrameIndex(prop.hVal.QuadPart)); qDebug() << kLogPreamble << "Frame count" << getFrameCount(); PropVariantClear(&prop); return true; }
SoundSource::OpenResult SoundSourceWV::tryOpen(const AudioSourceConfig& audioSrcCfg) { DEBUG_ASSERT(!m_wpc); char msg[80]; // hold possible error message int openFlags = OPEN_WVC | OPEN_NORMALIZE; if ((kChannelCountMono == audioSrcCfg.getChannelCount()) || (kChannelCountStereo == audioSrcCfg.getChannelCount())) { openFlags |= OPEN_2CH_MAX; } // We use WavpackOpenFileInputEx to support Unicode paths on windows // http://www.wavpack.com/lib_use.txt QString wavPackFileName = getLocalFileName(); m_pWVFile = new QFile(wavPackFileName); m_pWVFile->open(QFile::ReadOnly); QString correctionFileName(wavPackFileName + "c"); if (QFile::exists(correctionFileName)) { // If there is a correction file, open it as well m_pWVCFile = new QFile(correctionFileName); m_pWVCFile->open(QFile::ReadOnly); } m_wpc = WavpackOpenFileInputEx(&s_streamReader, m_pWVFile, m_pWVCFile, msg, openFlags, 0); if (!m_wpc) { qDebug() << "SSWV::open: failed to open file : " << msg; return OpenResult::FAILED; } setChannelCount(WavpackGetReducedChannels(m_wpc)); setSamplingRate(WavpackGetSampleRate(m_wpc)); setFrameCount(WavpackGetNumSamples(m_wpc)); if (WavpackGetMode(m_wpc) & MODE_FLOAT) { m_sampleScaleFactor = CSAMPLE_PEAK; } else { const int bitsPerSample = WavpackGetBitsPerSample(m_wpc); const uint32_t wavpackPeakSampleValue = 1u << (bitsPerSample - 1); m_sampleScaleFactor = CSAMPLE_PEAK / wavpackPeakSampleValue; } return OpenResult::SUCCEEDED; }
Result SoundSourceOggVorbis::tryOpen(const AudioSourceConfig& /*audioSrcCfg*/) { m_pFile = new QFile(getLocalFileName()); if(!m_pFile->open(QFile::ReadOnly)) { qWarning() << "Failed to open OggVorbis file:" << getUrlString(); return ERR; } if (ov_open_callbacks(m_pFile, &m_vf, NULL, 0, s_callbacks) < 0) { qDebug() << "oggvorbis: Input does not appear to be an Ogg bitstream."; return ERR; } if (!ov_seekable(&m_vf)) { qWarning() << "OggVorbis file is not seekable:" << getUrlString(); return ERR; } // lookup the ogg's channels and sample rate const vorbis_info* vi = ov_info(&m_vf, kCurrentBitstreamLink); if (!vi) { qWarning() << "Failed to read OggVorbis file:" << getUrlString(); return ERR; } setChannelCount(vi->channels); setSamplingRate(vi->rate); if (0 < vi->bitrate_nominal) { setBitrate(vi->bitrate_nominal / 1000); } else { if ((0 < vi->bitrate_lower) && (vi->bitrate_lower == vi->bitrate_upper)) { setBitrate(vi->bitrate_lower / 1000); } } ogg_int64_t pcmTotal = ov_pcm_total(&m_vf, kEntireBitstreamLink); if (0 <= pcmTotal) { setFrameCount(pcmTotal); } else { qWarning() << "Failed to read total length of OggVorbis file:" << getUrlString(); return ERR; } return OK; }
Result SoundSourceOggVorbis::tryOpen(const AudioSourceConfig& /*audioSrcCfg*/) { const QByteArray qbaFilename(getLocalFileNameBytes()); if (0 != ov_fopen(qbaFilename.constData(), &m_vf)) { qWarning() << "Failed to open OggVorbis file:" << getUrlString(); return ERR; } if (!ov_seekable(&m_vf)) { qWarning() << "OggVorbis file is not seekable:" << getUrlString(); return ERR; } // lookup the ogg's channels and sample rate const vorbis_info* vi = ov_info(&m_vf, kCurrentBitstreamLink); if (!vi) { qWarning() << "Failed to read OggVorbis file:" << getUrlString(); return ERR; } setChannelCount(vi->channels); setFrameRate(vi->rate); if (0 < vi->bitrate_nominal) { setBitrate(vi->bitrate_nominal / 1000); } else { if ((0 < vi->bitrate_lower) && (vi->bitrate_lower == vi->bitrate_upper)) { setBitrate(vi->bitrate_lower / 1000); } } ogg_int64_t pcmTotal = ov_pcm_total(&m_vf, kEntireBitstreamLink); if (0 <= pcmTotal) { setFrameCount(pcmTotal); } else { qWarning() << "Failed to read total length of OggVorbis file:" << getUrlString(); return ERR; } return OK; }
TEST_F(ImageFrameGeneratorTest, removeMultiFrameDecoder) { setFrameCount(3); setFrameStatus(ImageFrame::FrameComplete); char buffer[100 * 100 * 4]; m_generator->decodeAndScale(0, imageInfo(), buffer, 100 * 4); EXPECT_EQ(1, m_decodeRequestCount); EXPECT_EQ(0, m_decodersDestroyed); setFrameStatus(ImageFrame::FrameComplete); m_generator->decodeAndScale(1, imageInfo(), buffer, 100 * 4); EXPECT_EQ(2, m_decodeRequestCount); EXPECT_EQ(0, m_decodersDestroyed); setFrameStatus(ImageFrame::FrameComplete); // Multi frame decoder should be removed. m_generator->decodeAndScale(2, imageInfo(), buffer, 100 * 4); EXPECT_EQ(3, m_decodeRequestCount); EXPECT_EQ(1, m_decodersDestroyed); }
bool SoundSourceMediaFoundation::readProperties() { PROPVARIANT prop; HRESULT hr = S_OK; //Get the duration, provided as a 64-bit integer of 100-nanosecond units hr = m_pReader->GetPresentationAttribute(MF_SOURCE_READER_MEDIASOURCE, MF_PD_DURATION, &prop); if (FAILED(hr)) { qWarning() << "SSMF: error getting duration"; return false; } m_mfDuration = prop.hVal.QuadPart; setFrameCount(frameFromMF(m_mfDuration, getSamplingRate())); qDebug() << "SSMF: Frame count" << getFrameCount(); PropVariantClear(&prop); // presentation attribute MF_PD_AUDIO_ENCODING_BITRATE only exists for // presentation descriptors, one of which MFSourceReader is not. // Therefore, we calculate it ourselves. setBitrate(kBitsPerSample * frames2samples(getSamplingRate())); return true; }
Result SoundSourceSndFile::tryOpen(const AudioSourceConfig& /*audioSrcCfg*/) { DEBUG_ASSERT(!m_pSndFile); SF_INFO sfInfo; memset(&sfInfo, 0, sizeof(sfInfo)); #ifdef __WINDOWS__ // Note: we cannot use QString::toStdWString since QT 4 is compiled with // '/Zc:wchar_t-' flag and QT 5 not const QString localFileName(QDir::toNativeSeparators(getLocalFileName())); const ushort* const fileNameUtf16 = localFileName.utf16(); static_assert(sizeof(wchar_t) == sizeof(ushort), "QString::utf16(): wchar_t and ushort have different sizes"); m_pSndFile = sf_wchar_open( reinterpret_cast<wchar_t*>(const_cast<ushort*>(fileNameUtf16)), SFM_READ, &sfInfo); #else m_pSndFile = sf_open(getLocalFileName().toLocal8Bit(), SFM_READ, &sfInfo); #endif if (!m_pSndFile) { // sf_format_check is only for writes qWarning() << "Error opening libsndfile file:" << getUrlString() << sf_strerror(m_pSndFile); return ERR; } if (sf_error(m_pSndFile) > 0) { qWarning() << "Error opening libsndfile file:" << getUrlString() << sf_strerror(m_pSndFile); return ERR; } setChannelCount(sfInfo.channels); setSamplingRate(sfInfo.samplerate); setFrameCount(sfInfo.frames); return OK; }
Result SoundSourceFFmpeg::tryOpen(const AudioSourceConfig& /*audioSrcCfg*/) { unsigned int i; AVDictionary *l_iFormatOpts = NULL; const QByteArray qBAFilename(getLocalFileNameBytes()); qDebug() << "New SoundSourceFFmpeg :" << qBAFilename; DEBUG_ASSERT(!m_pFormatCtx); m_pFormatCtx = avformat_alloc_context(); #if LIBAVCODEC_VERSION_INT < 3622144 m_pFormatCtx->max_analyze_duration = 999999999; #endif // Open file and make m_pFormatCtx if (avformat_open_input(&m_pFormatCtx, qBAFilename.constData(), NULL, &l_iFormatOpts)!=0) { qDebug() << "av_open_input_file: cannot open" << qBAFilename; return ERR; } #if LIBAVCODEC_VERSION_INT > 3544932 av_dict_free(&l_iFormatOpts); #endif // Retrieve stream information if (avformat_find_stream_info(m_pFormatCtx, NULL)<0) { qDebug() << "av_find_stream_info: cannot open" << qBAFilename; return ERR; } //debug only (Enable if needed) //av_dump_format(m_pFormatCtx, 0, qBAFilename.constData(), false); // Find the first audio stream m_iAudioStream=-1; for (i=0; i<m_pFormatCtx->nb_streams; i++) if (m_pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO) { m_iAudioStream=i; break; } if (m_iAudioStream == -1) { qDebug() << "ffmpeg: cannot find an audio stream: cannot open" << qBAFilename; return ERR; } // Get a pointer to the codec context for the audio stream m_pCodecCtx=m_pFormatCtx->streams[m_iAudioStream]->codec; // Find the decoder for the audio stream if (!(m_pCodec=avcodec_find_decoder(m_pCodecCtx->codec_id))) { qDebug() << "ffmpeg: cannot find a decoder for" << qBAFilename; return ERR; } if (avcodec_open2(m_pCodecCtx, m_pCodec, NULL)<0) { qDebug() << "ffmpeg: cannot open" << qBAFilename; return ERR; } m_pResample = new EncoderFfmpegResample(m_pCodecCtx); m_pResample->open(m_pCodecCtx->sample_fmt, AV_SAMPLE_FMT_FLT); setChannelCount(m_pCodecCtx->channels); setFrameRate(m_pCodecCtx->sample_rate); setFrameCount((m_pFormatCtx->duration * m_pCodecCtx->sample_rate) / AV_TIME_BASE); qDebug() << "ffmpeg: Samplerate: " << getFrameRate() << ", Channels: " << getChannelCount() << "\n"; if (getChannelCount() > 2) { qDebug() << "ffmpeg: No support for more than 2 channels!"; return ERR; } return OK; }
Result SoundSourceModPlug::tryOpen(const AudioSourceConfig& /*audioSrcCfg*/) { ScopedTimer t("SoundSourceModPlug::open()"); // read module file to byte array const QString fileName(getLocalFileName()); QFile modFile(fileName); qDebug() << "[ModPlug] Loading ModPlug module " << modFile.fileName(); modFile.open(QIODevice::ReadOnly); m_fileBuf = modFile.readAll(); modFile.close(); // get ModPlugFile descriptor for later access m_pModFile = ModPlug::ModPlug_Load(m_fileBuf.constData(), m_fileBuf.length()); if (m_pModFile == NULL) { // an error occured t.cancel(); qDebug() << "[ModPlug] Could not load module file: " << fileName; return ERR; } DEBUG_ASSERT(0 == (kChunkSizeInBytes % sizeof(m_sampleBuf[0]))); const SINT chunkSizeInSamples = kChunkSizeInBytes / sizeof(m_sampleBuf[0]); const SampleBuffer::size_type bufferSizeLimitInSamples = s_bufferSizeLimit / sizeof(m_sampleBuf[0]); // Estimate size of sample buffer (for better performance) aligned // with the chunk size. Beware: Module length estimation is unreliable // due to loops! const SampleBuffer::size_type estimateMilliseconds = ModPlug::ModPlug_GetLength(m_pModFile); const SampleBuffer::size_type estimateSamples = estimateMilliseconds * kChannelCount * kSamplingRate; const SampleBuffer::size_type estimateChunks = (estimateSamples + (chunkSizeInSamples - 1)) / chunkSizeInSamples; const SampleBuffer::size_type sampleBufferCapacity = math_min( estimateChunks * chunkSizeInSamples, bufferSizeLimitInSamples); m_sampleBuf.reserve(sampleBufferCapacity); qDebug() << "[ModPlug] Reserved " << m_sampleBuf.capacity() << " #samples"; // decode samples into sample buffer while (m_sampleBuf.size() < bufferSizeLimitInSamples) { // reserve enough space in sample buffer const SampleBuffer::size_type currentSize = m_sampleBuf.size(); m_sampleBuf.resize(currentSize + chunkSizeInSamples); const int bytesRead = ModPlug::ModPlug_Read(m_pModFile, &m_sampleBuf[currentSize], kChunkSizeInBytes); // adjust size of sample buffer after reading if (0 < bytesRead) { DEBUG_ASSERT(0 == (bytesRead % sizeof(m_sampleBuf[0]))); const SampleBuffer::size_type samplesRead = bytesRead / sizeof(m_sampleBuf[0]); m_sampleBuf.resize(currentSize + samplesRead); } else { // nothing read -> EOF m_sampleBuf.resize(currentSize); break; // exit loop } } qDebug() << "[ModPlug] Filled Sample buffer with " << m_sampleBuf.size() << " samples."; qDebug() << "[ModPlug] Sample buffer has " << m_sampleBuf.capacity() - m_sampleBuf.size() << " samples unused capacity."; setChannelCount(kChannelCount); setSamplingRate(kSamplingRate); setFrameCount(samples2frames(m_sampleBuf.size())); m_seekPos = 0; return OK; }
SoundSource::OpenResult SoundSourceMp3::tryOpen(const AudioSourceConfig& /*audioSrcCfg*/) { DEBUG_ASSERT(!hasValidChannelCount()); DEBUG_ASSERT(!hasValidSamplingRate()); DEBUG_ASSERT(!m_file.isOpen()); if (!m_file.open(QIODevice::ReadOnly)) { qWarning() << "Failed to open file:" << m_file.fileName(); return OpenResult::FAILED; } // Get a pointer to the file using memory mapped IO m_fileSize = m_file.size(); m_pFileData = m_file.map(0, m_fileSize); // NOTE(uklotzde): If the file disappears unexpectedly while mapped // a SIGBUS error might occur that is not handled and will terminate // Mixxx immediately. This behavior is documented in the manpage of // mmap(). It has already appeared due to hardware errors and is // described in the following bug report: // https://bugs.launchpad.net/mixxx/+bug/1452005 // Transfer it to the mad stream-buffer: mad_stream_options(&m_madStream, MAD_OPTION_IGNORECRC); mad_stream_buffer(&m_madStream, m_pFileData, m_fileSize); DEBUG_ASSERT(m_pFileData == m_madStream.this_frame); DEBUG_ASSERT(m_seekFrameList.empty()); m_avgSeekFrameCount = 0; m_curFrameIndex = getMinFrameIndex(); int headerPerSamplingRate[kSamplingRateCount]; for (int i = 0; i < kSamplingRateCount; ++i) { headerPerSamplingRate[i] = 0; } // Decode all the headers and calculate audio properties unsigned long sumBitrate = 0; mad_header madHeader; mad_header_init(&madHeader); SINT maxChannelCount = getChannelCount(); do { if (!decodeFrameHeader(&madHeader, &m_madStream, true)) { if (isStreamValid(m_madStream)) { // Skip frame continue; } else { // Abort decoding break; } } // Grab data from madHeader const unsigned int madSampleRate = madHeader.samplerate; // TODO(XXX): Replace DEBUG_ASSERT with static_assert // MAD must not change its enum values! DEBUG_ASSERT(MAD_UNITS_8000_HZ == 8000); const mad_units madUnits = static_cast<mad_units>(madSampleRate); const long madFrameLength = mad_timer_count(madHeader.duration, madUnits); if (0 >= madFrameLength) { qWarning() << "Skipping MP3 frame with invalid length" << madFrameLength << "in:" << m_file.fileName(); // Skip frame continue; } const SINT madChannelCount = MAD_NCHANNELS(&madHeader); if (isValidChannelCount(maxChannelCount) && (madChannelCount != maxChannelCount)) { qWarning() << "Differing number of channels" << madChannelCount << "<>" << maxChannelCount << "in some MP3 frame headers:" << m_file.fileName(); } maxChannelCount = math_max(madChannelCount, maxChannelCount); const int samplingRateIndex = getIndexBySamplingRate(madSampleRate); if (samplingRateIndex >= kSamplingRateCount) { qWarning() << "Invalid sample rate:" << m_file.fileName() << madSampleRate; // Abort mad_header_finish(&madHeader); return OpenResult::FAILED; } // Count valid frames separated by its sampling rate headerPerSamplingRate[samplingRateIndex]++; addSeekFrame(m_curFrameIndex, m_madStream.this_frame); // Accumulate data from the header sumBitrate += madHeader.bitrate; // Update current stream position m_curFrameIndex += madFrameLength; DEBUG_ASSERT(m_madStream.this_frame); DEBUG_ASSERT(0 <= (m_madStream.this_frame - m_pFileData)); } while (quint64(m_madStream.this_frame - m_pFileData) < m_fileSize); mad_header_finish(&madHeader); if (MAD_ERROR_NONE != m_madStream.error) { // Unreachable code for recoverable errors DEBUG_ASSERT(!MAD_RECOVERABLE(m_madStream.error)); if (MAD_ERROR_BUFLEN != m_madStream.error) { qWarning() << "Unrecoverable MP3 header error:" << mad_stream_errorstr(&m_madStream); // Abort return OpenResult::FAILED; } } if (m_seekFrameList.empty()) { // This is not a working MP3 file. qWarning() << "SSMP3: This is not a working MP3 file:" << m_file.fileName(); // Abort return OpenResult::FAILED; } int mostCommonSamplingRateIndex = kSamplingRateCount; // invalid int mostCommonSamplingRateCount = 0; int differentRates = 0; for (int i = 0; i < kSamplingRateCount; ++i) { // Find most common sampling rate if (mostCommonSamplingRateCount < headerPerSamplingRate[i]) { mostCommonSamplingRateCount = headerPerSamplingRate[i]; mostCommonSamplingRateIndex = i; differentRates++; } } if (differentRates > 1) { qWarning() << "Differing sampling rate in some headers:" << m_file.fileName(); for (int i = 0; i < kSamplingRateCount; ++i) { if (0 < headerPerSamplingRate[i]) { qWarning() << headerPerSamplingRate[i] << "MP3 headers with sampling rate" << getSamplingRateByIndex(i); } } qWarning() << "MP3 files with varying sample rate are not supported!"; qWarning() << "Since this happens most likely due to a corrupt file"; qWarning() << "Mixxx tries to plays it with the most common sample rate for this file"; } if (mostCommonSamplingRateIndex < kSamplingRateCount) { setSamplingRate(getSamplingRateByIndex(mostCommonSamplingRateIndex)); } else { qWarning() << "No single valid sampling rate in header"; // Abort return OpenResult::FAILED; } // Initialize the AudioSource setChannelCount(maxChannelCount); setFrameCount(m_curFrameIndex); // Calculate average values m_avgSeekFrameCount = getFrameCount() / m_seekFrameList.size(); const unsigned long avgBitrate = sumBitrate / m_seekFrameList.size(); setBitrate(avgBitrate / 1000); // Terminate m_seekFrameList addSeekFrame(m_curFrameIndex, 0); // Reset positions m_curFrameIndex = getMinFrameIndex(); // Restart decoding at the beginning of the audio stream m_curFrameIndex = restartDecoding(m_seekFrameList.front()); if (m_curFrameIndex != m_seekFrameList.front().frameIndex) { qWarning() << "Failed to start decoding:" << m_file.fileName(); // Abort return OpenResult::FAILED; } return OpenResult::SUCCEEDED; }
Result SoundSourceM4A::tryOpen(const AudioSourceConfig& audioSrcCfg) { DEBUG_ASSERT(MP4_INVALID_FILE_HANDLE == m_hFile); /* open MP4 file, check for >= ver 1.9.1 */ #if MP4V2_PROJECT_version_hex <= 0x00010901 m_hFile = MP4Read(getLocalFileNameBytes().constData(), 0); #else m_hFile = MP4Read(getLocalFileNameBytes().constData()); #endif if (MP4_INVALID_FILE_HANDLE == m_hFile) { qWarning() << "Failed to open file for reading:" << getUrlString(); return ERR; } m_trackId = findFirstAudioTrackId(m_hFile); if (MP4_INVALID_TRACK_ID == m_trackId) { qWarning() << "No AAC track found:" << getUrlString(); return ERR; } const MP4SampleId numberOfSamples = MP4GetTrackNumberOfSamples(m_hFile, m_trackId); if (0 >= numberOfSamples) { qWarning() << "Failed to read number of samples from file:" << getUrlString(); return ERR; } m_maxSampleBlockId = kSampleBlockIdMin + (numberOfSamples - 1); // Determine the maximum input size (in bytes) of a // sample block for the selected track. const u_int32_t maxSampleBlockInputSize = MP4GetTrackMaxSampleSize(m_hFile, m_trackId); m_inputBuffer.resize(maxSampleBlockInputSize, 0); DEBUG_ASSERT(NULL == m_hDecoder); // not already opened m_hDecoder = NeAACDecOpen(); if (!m_hDecoder) { qWarning() << "Failed to open the AAC decoder!"; return ERR; } NeAACDecConfigurationPtr pDecoderConfig = NeAACDecGetCurrentConfiguration( m_hDecoder); pDecoderConfig->outputFormat = FAAD_FMT_FLOAT; if ((kChannelCountMono == audioSrcCfg.channelCountHint) || (kChannelCountStereo == audioSrcCfg.channelCountHint)) { pDecoderConfig->downMatrix = 1; } else { pDecoderConfig->downMatrix = 0; } pDecoderConfig->defObjectType = LC; if (!NeAACDecSetConfiguration(m_hDecoder, pDecoderConfig)) { qWarning() << "Failed to configure AAC decoder!"; return ERR; } u_int8_t* configBuffer = NULL; u_int32_t configBufferSize = 0; if (!MP4GetTrackESConfiguration(m_hFile, m_trackId, &configBuffer, &configBufferSize)) { /* failed to get mpeg-4 audio config... this is ok. * NeAACDecInit2() will simply use default values instead. */ qWarning() << "Failed to read the MP4 audio configuration." << "Continuing with default values."; } SAMPLERATE_TYPE sampleRate; unsigned char channelCount; if (0 > NeAACDecInit2(m_hDecoder, configBuffer, configBufferSize, &sampleRate, &channelCount)) { free(configBuffer); qWarning() << "Failed to initialize the AAC decoder!"; return ERR; } else { free(configBuffer); } setChannelCount(channelCount); setFrameRate(sampleRate); setFrameCount(getFrameCountForSampleBlockId(m_maxSampleBlockId)); // Resize temporary buffer for decoded sample data const SINT sampleBufferCapacity = frames2samples(kFramesPerSampleBlock); m_sampleBuffer.resetCapacity(sampleBufferCapacity); // Invalidate current position to enforce the following // seek operation m_curFrameIndex = getMaxFrameIndex(); // (Re-)Start decoding at the beginning of the file seekSampleFrame(getMinFrameIndex()); return OK; }
// soundsource overrides Result SoundSourceCoreAudio::tryOpen(const AudioSourceConfig& audioSrcCfg) { const QString fileName(getLocalFileName()); //Open the audio file. OSStatus err; /** This code blocks works with OS X 10.5+ only. DO NOT DELETE IT for now. */ CFStringRef urlStr = CFStringCreateWithCharacters(0, reinterpret_cast<const UniChar *>(fileName.unicode()), fileName.size()); CFURLRef urlRef = CFURLCreateWithFileSystemPath(NULL, urlStr, kCFURLPOSIXPathStyle, false); err = ExtAudioFileOpenURL(urlRef, &m_audioFile); CFRelease(urlStr); CFRelease(urlRef); /** TODO: Use FSRef for compatibility with 10.4 Tiger. Note that ExtAudioFileOpen() is deprecated above Tiger, so we must maintain both code paths if someone finishes this part of the code. FSRef fsRef; CFURLGetFSRef(reinterpret_cast<CFURLRef>(url.get()), &fsRef); err = ExtAudioFileOpen(&fsRef, &m_audioFile); */ if (err != noErr) { qDebug() << "SSCA: Error opening file " << fileName; return ERR; } // get the input file format UInt32 inputFormatSize = sizeof(m_inputFormat); err = ExtAudioFileGetProperty(m_audioFile, kExtAudioFileProperty_FileDataFormat, &inputFormatSize, &m_inputFormat); if (err != noErr) { qDebug() << "SSCA: Error getting file format (" << fileName << ")"; return ERR; } m_bFileIsMp3 = m_inputFormat.mFormatID == kAudioFormatMPEGLayer3; // create the output format const UInt32 numChannels = (kChannelCountZero < audioSrcCfg.channelCountHint) ? audioSrcCfg.channelCountHint : 2; m_outputFormat = CAStreamBasicDescription(m_inputFormat.mSampleRate, numChannels, CAStreamBasicDescription::kPCMFormatFloat32, true); // set the client format err = ExtAudioFileSetProperty(m_audioFile, kExtAudioFileProperty_ClientDataFormat, sizeof(m_outputFormat), &m_outputFormat); if (err != noErr) { qDebug() << "SSCA: Error setting file property"; return ERR; } //get the total length in frames of the audio file - copypasta: http://discussions.apple.com/thread.jspa?threadID=2364583&tstart=47 SInt64 totalFrameCount; UInt32 totalFrameCountSize = sizeof(totalFrameCount); err = ExtAudioFileGetProperty(m_audioFile, kExtAudioFileProperty_FileLengthFrames, &totalFrameCountSize, &totalFrameCount); if (err != noErr) { qDebug() << "SSCA: Error getting number of frames"; return ERR; } // // WORKAROUND for bug in ExtFileAudio // AudioConverterRef acRef; UInt32 acrsize = sizeof(AudioConverterRef); err = ExtAudioFileGetProperty(m_audioFile, kExtAudioFileProperty_AudioConverter, &acrsize, &acRef); //_ThrowExceptionIfErr(@"kExtAudioFileProperty_AudioConverter", err); AudioConverterPrimeInfo primeInfo; UInt32 piSize = sizeof(AudioConverterPrimeInfo); memset(&primeInfo, 0, piSize); err = AudioConverterGetProperty(acRef, kAudioConverterPrimeInfo, &piSize, &primeInfo); if (err != kAudioConverterErr_PropertyNotSupported) { // Only if decompressing //_ThrowExceptionIfErr(@"kAudioConverterPrimeInfo", err); m_headerFrames = primeInfo.leadingFrames; } else { m_headerFrames = 0; } setChannelCount(m_outputFormat.NumberChannels()); setFrameRate(m_inputFormat.mSampleRate); // NOTE(uklotzde): This is what I found when migrating // the code from SoundSource (sample-oriented) to the new // AudioSource (frame-oriented) API. It is not documented // when m_headerFrames > 0 and what the consequences are. setFrameCount(totalFrameCount/* - m_headerFrames*/); //Seek to position 0, which forces us to skip over all the header frames. //This makes sure we're ready to just let the Analyser rip and it'll //get the number of samples it expects (ie. no header frames). seekSampleFrame(0); return OK; }
bool SoundSourceM4A::openDecoder() { DEBUG_ASSERT(m_hDecoder == nullptr); // not already opened m_hDecoder = NeAACDecOpen(); if (m_hDecoder == nullptr) { qWarning() << "Failed to open the AAC decoder!"; return false; } NeAACDecConfigurationPtr pDecoderConfig = NeAACDecGetCurrentConfiguration( m_hDecoder); pDecoderConfig->outputFormat = FAAD_FMT_FLOAT; if ((kChannelCountMono == m_audioSrcCfg.getChannelCount()) || (kChannelCountStereo == m_audioSrcCfg.getChannelCount())) { pDecoderConfig->downMatrix = 1; } else { pDecoderConfig->downMatrix = 0; } pDecoderConfig->defObjectType = LC; if (!NeAACDecSetConfiguration(m_hDecoder, pDecoderConfig)) { qWarning() << "Failed to configure AAC decoder!"; return false; } u_int8_t* configBuffer = nullptr; u_int32_t configBufferSize = 0; if (!MP4GetTrackESConfiguration(m_hFile, m_trackId, &configBuffer, &configBufferSize)) { // Failed to get mpeg-4 audio config... this is ok. // NeAACDecInit2() will simply use default values instead. qWarning() << "Failed to read the MP4 audio configuration." << "Continuing with default values."; } SAMPLERATE_TYPE samplingRate; unsigned char channelCount; if (0 > NeAACDecInit2(m_hDecoder, configBuffer, configBufferSize, &samplingRate, &channelCount)) { free(configBuffer); qWarning() << "Failed to initialize the AAC decoder!"; return false; } else { free(configBuffer); } // Calculate how many sample blocks we need to decode in advance // of a random seek in order to get the recommended number of // prefetch frames m_numberOfPrefetchSampleBlocks = (kNumberOfPrefetchFrames + (m_framesPerSampleBlock - 1)) / m_framesPerSampleBlock; setChannelCount(channelCount); setSamplingRate(samplingRate); setFrameCount(((m_maxSampleBlockId - kSampleBlockIdMin) + 1) * m_framesPerSampleBlock); // Resize temporary buffer for decoded sample data const SINT sampleBufferCapacity = frames2samples(m_framesPerSampleBlock); m_sampleBuffer.resetCapacity(sampleBufferCapacity); // Discard all buffered samples m_inputBufferLength = 0; // Invalidate current position(s) for the following seek operation m_curSampleBlockId = MP4_INVALID_SAMPLE_ID; m_curFrameIndex = getMaxFrameIndex(); // (Re-)Start decoding at the beginning of the file seekSampleFrame(getMinFrameIndex()); return m_curFrameIndex == getMinFrameIndex(); }
void SoundSourceFLAC::flacMetadata(const FLAC__StreamMetadata* metadata) { // https://xiph.org/flac/api/group__flac__stream__decoder.html#ga43e2329c15731c002ac4182a47990f85 // "...one STREAMINFO block, followed by zero or more other metadata blocks." // "...by default the decoder only calls the metadata callback for the STREAMINFO block..." // "...always before the first audio frame (i.e. write callback)." switch (metadata->type) { case FLAC__METADATA_TYPE_STREAMINFO: { const SINT channelCount = metadata->data.stream_info.channels; if (isValidChannelCount(channelCount)) { if (hasChannelCount()) { // already set before -> check for consistency if (getChannelCount() != channelCount) { qWarning() << "Unexpected channel count:" << channelCount << " <> " << getChannelCount(); } } else { // not set before setChannelCount(channelCount); } } else { qWarning() << "Invalid channel count:" << channelCount; } const SINT samplingRate = metadata->data.stream_info.sample_rate; if (isValidSamplingRate(samplingRate)) { if (hasSamplingRate()) { // already set before -> check for consistency if (getSamplingRate() != samplingRate) { qWarning() << "Unexpected sampling rate:" << samplingRate << " <> " << getSamplingRate(); } } else { // not set before setSamplingRate(samplingRate); } } else { qWarning() << "Invalid sampling rate:" << samplingRate; } const SINT frameCount = metadata->data.stream_info.total_samples; DEBUG_ASSERT(isValidFrameCount(frameCount)); if (isEmpty()) { // not set before setFrameCount(frameCount); } else { // already set before -> check for consistency if (getFrameCount() != frameCount) { qWarning() << "Unexpected frame count:" << frameCount << " <> " << getFrameCount(); } } const unsigned bitsPerSample = metadata->data.stream_info.bits_per_sample; DEBUG_ASSERT(kBitsPerSampleDefault != bitsPerSample); if (kBitsPerSampleDefault == m_bitsPerSample) { // not set before m_bitsPerSample = bitsPerSample; m_sampleScaleFactor = CSAMPLE_PEAK / CSAMPLE(FLAC__int32(1) << bitsPerSample); } else { // already set before -> check for consistency if (bitsPerSample != m_bitsPerSample) { qWarning() << "Unexpected bits per sample:" << bitsPerSample << " <> " << m_bitsPerSample; } } m_maxBlocksize = metadata->data.stream_info.max_blocksize; if (0 >= m_maxBlocksize) { qWarning() << "Invalid max. blocksize" << m_maxBlocksize; } const SINT sampleBufferCapacity = m_maxBlocksize * getChannelCount(); m_sampleBuffer.resetCapacity(sampleBufferCapacity); break; } default: // Ignore all other metadata types break; } }
Result SoundSourceM4A::tryOpen(const AudioSourceConfig& audioSrcCfg) { DEBUG_ASSERT(MP4_INVALID_FILE_HANDLE == m_hFile); // open MP4 file, check for >= ver 1.9.1 // From mp4v2/file.h: // * On Windows, this should be a UTF-8 encoded string. // * On other platforms, it should be an 8-bit encoding that is // * appropriate for the platform, locale, file system, etc. // * (prefer to use UTF-8 when possible). #if MP4V2_PROJECT_version_hex <= 0x00010901 m_hFile = MP4Read(getLocalFileName().toUtf8().constData(), 0); #else m_hFile = MP4Read(getLocalFileName().toUtf8().constData()); #endif if (MP4_INVALID_FILE_HANDLE == m_hFile) { qWarning() << "Failed to open file for reading:" << getUrlString(); return ERR; } m_trackId = findFirstAudioTrackId(m_hFile); if (MP4_INVALID_TRACK_ID == m_trackId) { qWarning() << "No AAC track found:" << getUrlString(); return ERR; } // Read fixed sample duration. If the sample duration is not // fixed (that is, if the number of frames per sample block varies // through the file), the call returns MP4_INVALID_DURATION. We // can't currently handle these. m_framesPerSampleBlock = MP4GetTrackFixedSampleDuration(m_hFile, m_trackId); if (MP4_INVALID_DURATION == m_framesPerSampleBlock) { qWarning() << "Unable to decode tracks with non-fixed sample durations: " << getUrlString(); return ERR; } const MP4SampleId numberOfSamples = MP4GetTrackNumberOfSamples(m_hFile, m_trackId); if (0 >= numberOfSamples) { qWarning() << "Failed to read number of samples from file:" << getUrlString(); return ERR; } m_maxSampleBlockId = kSampleBlockIdMin + (numberOfSamples - 1); // Determine the maximum input size (in bytes) of a // sample block for the selected track. const u_int32_t maxSampleBlockInputSize = MP4GetTrackMaxSampleSize(m_hFile, m_trackId); m_inputBuffer.resize(maxSampleBlockInputSize, 0); DEBUG_ASSERT(nullptr == m_hDecoder); // not already opened m_hDecoder = NeAACDecOpen(); if (!m_hDecoder) { qWarning() << "Failed to open the AAC decoder!"; return ERR; } NeAACDecConfigurationPtr pDecoderConfig = NeAACDecGetCurrentConfiguration( m_hDecoder); pDecoderConfig->outputFormat = FAAD_FMT_FLOAT; if ((kChannelCountMono == audioSrcCfg.channelCountHint) || (kChannelCountStereo == audioSrcCfg.channelCountHint)) { pDecoderConfig->downMatrix = 1; } else { pDecoderConfig->downMatrix = 0; } pDecoderConfig->defObjectType = LC; if (!NeAACDecSetConfiguration(m_hDecoder, pDecoderConfig)) { qWarning() << "Failed to configure AAC decoder!"; return ERR; } u_int8_t* configBuffer = nullptr; u_int32_t configBufferSize = 0; if (!MP4GetTrackESConfiguration(m_hFile, m_trackId, &configBuffer, &configBufferSize)) { /* failed to get mpeg-4 audio config... this is ok. * NeAACDecInit2() will simply use default values instead. */ qWarning() << "Failed to read the MP4 audio configuration." << "Continuing with default values."; } SAMPLERATE_TYPE sampleRate; unsigned char channelCount; if (0 > NeAACDecInit2(m_hDecoder, configBuffer, configBufferSize, &sampleRate, &channelCount)) { free(configBuffer); qWarning() << "Failed to initialize the AAC decoder!"; return ERR; } else { free(configBuffer); } // Calculate how many sample blocks we need to decode in advance // of a random seek in order to get the recommended number of // prefetch frames m_numberOfPrefetchSampleBlocks = (kNumberOfPrefetchFrames + (m_framesPerSampleBlock - 1)) / m_framesPerSampleBlock; setChannelCount(channelCount); setFrameRate(sampleRate); setFrameCount(((m_maxSampleBlockId - kSampleBlockIdMin) + 1) * m_framesPerSampleBlock); // Resize temporary buffer for decoded sample data const SINT sampleBufferCapacity = frames2samples(m_framesPerSampleBlock); m_sampleBuffer.resetCapacity(sampleBufferCapacity); // Invalidate current position to enforce the following // seek operation m_curFrameIndex = getMaxFrameIndex(); // (Re-)Start decoding at the beginning of the file seekSampleFrame(getMinFrameIndex()); return OK; }
SoundSource::OpenResult SoundSourceFFmpeg::tryOpen(const AudioSourceConfig& /*audioSrcCfg*/) { AVDictionary *l_iFormatOpts = nullptr; const QString localFileName(getLocalFileName()); qDebug() << "New SoundSourceFFmpeg :" << localFileName; DEBUG_ASSERT(!m_pFormatCtx); m_pFormatCtx = avformat_alloc_context(); if (m_pFormatCtx == nullptr) { qDebug() << "SoundSourceFFmpeg::tryOpen: Can't allocate memory"; return OpenResult::FAILED; } // TODO() why is this required, should't it be a runtime check #if LIBAVCODEC_VERSION_INT < 3622144 // 55.69.0 m_pFormatCtx->max_analyze_duration = 999999999; #endif // libav replaces open() with ff_win32_open() which accepts a // Utf8 path // see: avformat/os_support.h // The old method defining an URL_PROTOCOL is deprecated #if defined(_WIN32) && !defined(__MINGW32CE__) const QByteArray qBAFilename( avformat_version() >= ((52<<16)+(0<<8)+0) ? getLocalFileName().toUtf8() : getLocalFileName().toLocal8Bit()); #else const QByteArray qBAFilename(getLocalFileName().toLocal8Bit()); #endif // Open file and make m_pFormatCtx if (avformat_open_input(&m_pFormatCtx, qBAFilename.constData(), nullptr, &l_iFormatOpts) != 0) { qDebug() << "SoundSourceFFmpeg::tryOpen: cannot open" << localFileName; return OpenResult::FAILED; } // TODO() why is this required, should't it be a runtime check #if LIBAVCODEC_VERSION_INT > 3544932 // 54.23.100 av_dict_free(&l_iFormatOpts); #endif // Retrieve stream information if (avformat_find_stream_info(m_pFormatCtx, nullptr) < 0) { qDebug() << "SoundSourceFFmpeg::tryOpen: cannot open" << localFileName; return OpenResult::FAILED; } //debug only (Enable if needed) //av_dump_format(m_pFormatCtx, 0, qBAFilename.constData(), false); // Find the first audio stream m_iAudioStream = -1; for (unsigned int i = 0; i < m_pFormatCtx->nb_streams; i++) if (m_pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) { m_iAudioStream = i; break; } if (m_iAudioStream == -1) { qDebug() << "SoundSourceFFmpeg::tryOpen: cannot find an audio stream: cannot open" << localFileName; return OpenResult::FAILED; } // Get a pointer to the codec context for the audio stream m_pCodecCtx = m_pFormatCtx->streams[m_iAudioStream]->codec; // Find the decoder for the audio stream if (!(m_pCodec = avcodec_find_decoder(m_pCodecCtx->codec_id))) { qDebug() << "SoundSourceFFmpeg::tryOpen: cannot find a decoder for" << localFileName; return OpenResult::UNSUPPORTED_FORMAT; } if (avcodec_open2(m_pCodecCtx, m_pCodec, nullptr)<0) { qDebug() << "SoundSourceFFmpeg::tryOpen: cannot open" << localFileName; return OpenResult::FAILED; } m_pResample = std::make_unique<EncoderFfmpegResample>(m_pCodecCtx); m_pResample->openMixxx(m_pCodecCtx->sample_fmt, AV_SAMPLE_FMT_FLT); setChannelCount(m_pCodecCtx->channels); setSamplingRate(m_pCodecCtx->sample_rate); setFrameCount((qint64)round((double)((double)m_pFormatCtx->duration * (double)m_pCodecCtx->sample_rate) / (double)AV_TIME_BASE)); qDebug() << "SoundSourceFFmpeg::tryOpen: Sampling rate: " << getSamplingRate() << ", Channels: " << getChannelCount() << "\n"; if (getChannelCount() > 2) { qDebug() << "ffmpeg: No support for more than 2 channels!"; return OpenResult::FAILED; } return OpenResult::SUCCEEDED; }
void DIA_encodingBase::refresh(void) { uint32_t time=clock.getElapsedMS(); if(time>_nextUpdate) { uint32_t deltaTime=time-_lastClock; uint32_t deltaFrame=_currentFrameCount-_lastFrameCount; uint64_t deltaDts=_currentDts-_lastDts; if(sampleIndex>ADM_ENCODING_SAMPLE) { uint32_t qSum=0; for(int i=0;i<ADM_ENCODING_SAMPLE;i++) qSum+=samples[i].qz; qSum/=ADM_ENCODING_SAMPLE; aprintf("Q:%d\n",qSum); setAverageQz(qSum); } if(sampleIndex>ADM_ENCODING_SAMPLE) { int start=sampleIndex%ADM_ENCODING_SAMPLE; int end=(sampleIndex+ADM_ENCODING_SAMPLE-1)%ADM_ENCODING_SAMPLE; uint64_t deltaTime=samples[end].sampleTime-samples[start].sampleTime; uint64_t deltaSize=samples[end].size-samples[start].size; aprintf("dTime:%d dSize:%d\n",deltaTime,deltaSize); if(deltaTime>1000) { float delta; delta=deltaSize; delta/=deltaTime; delta*=8; // byte -> bit delta*=1000; // b/us -> kb/s aprintf("br:%d\n",(int)delta); setAverageBitrateKbits((uint32_t)delta); } } if(deltaFrame) { float thisAverage; //printf("**********************************DFrame=%d, DTime=%d\n",(int)deltaFrame,(int)deltaTime); thisAverage=((float)deltaFrame); thisAverage/=deltaTime; thisAverage*=1000; _fps_average=_fps_average*0.5+0.5*thisAverage; //printf("************** Fps:%d\n",(int)_fps_average); setFps(_fps_average); float percent=(float)_currentDts/(float)_totalDurationUs; if(percent>1.0) percent=1.0; percent*=100; setPercent((uint32_t)percent); setFrameCount(_currentFrameCount); setElapsedTimeMs(time); } if(deltaDts ) { float dtsPerSec=deltaDts; dtsPerSec/=deltaTime; dtsPerSec/=1000.; // dts advance per second float leftDts=_totalDurationUs-_currentDts; //printf("***************%u to encoding\n",(int)(leftDts/1000000)); //printf("Advanc=%d ms/sec\n",(int)(dtsPerSec*1000)); if(dtsPerSec>0.01) { leftDts=leftDts/dtsPerSec; _remainingTimeUs=(_remainingTimeUs/2)+(leftDts/2); leftDts=_remainingTimeUs; leftDts/=1000.; // us -> ms //printf("***************%u s left\n",(int)(leftDts/1000)); setRemainingTimeMS((uint32_t)leftDts); } } _nextUpdate=time+GUI_UPDATE_RATE; setAudioSize(_audioSize); setVideoSize(_videoSize); setTotalSize(_audioSize+_videoSize); _lastFrameCount=_currentFrameCount; _lastDts=_currentDts; _lastClock=time; } UI_purge(); }
//============================================================== // Конструктор с параметрами //============================================================== SettingAnimation::SettingAnimation(int fps, int frameCount) { setFps(fps); setFrameCount(frameCount); }